﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Http;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Extentions;
using TrainingReminderSystem.Model;
using TrainingReminderSystem.Dal;
using System.Threading.Tasks;
using Z.EntityFramework.Plus;

namespace TrainingReminderSystem.Bll
{
    /// <summary>
    /// 店铺文件 逻辑层
    /// </summary>
    public partial class SysFileBll : PcLoginedBll
    {
        public const string FilePath = "/Upload/SysFile/";

        #region 添加和编辑的时候 验证数据和设置默认值

        /// <summary>
        /// 添加和编辑的时候 验证数据和设置默认值
        /// </summary>
        /// <param name="model"></param>
        /// <param name="isAdd">添加还是编辑,可以不管此参数</param>/// <param name="db"></param>
        /// <returns>是否通过,true表示验证通过,false代表验证没有通过</returns>
        public AjaxResult<dynamic> Validate(SysFile model, bool isAdd, DbEntities db)
        {
            var r = new AjaxResult<dynamic>();
            if (model == null)
            {
                r.Message = LanguageHelper.NoSubmitData;
                return r;
            }
            model.ExTrimProperty();

            if (string.IsNullOrEmpty(model.SysFileName))
            {
                r.Message = LanguageHelper.RequireString1<SysFile>(nameof(SysFile.SysFileName));
                return r;
            }
            string md5 = string.Empty;
            string localFile = string.Empty;
            if (!string.IsNullOrEmpty(model.UploadFileLocalFile))
            {
                md5 = model.FileMD5;
                localFile = model.UploadFileLocalFile;
            }
            else
            {
                model.FilePath = Base64Helper.SaveFileFromBase64Md5(model.FilePath, ref md5, ref localFile, FilePath);
            }

            if (!string.IsNullOrEmpty(md5) && !string.IsNullOrEmpty(localFile))
            {
                #region 新保存的文件的时候;判断此MD5是否存在,存在则删除文件,此数据是否是我能访问到的,是就更新时间,不是新增一条数据

                //新保存的文件的时候
                var currentStore = CurrentStore;
                int sysStoreID = currentStore.SysStoreID;
                List<int> storeIDList = new List<int>();
                if (currentStore.IsMainStore() ||
                    currentStore.EnumSysStoreType == EnumSysStoreType.子店铺)
                {
                    storeIDList = GetAllStoreIDCache(sysStoreID, db);
                }
                else //if (currentStore.EnumSysStoreType == EnumSysStoreType.连锁店铺)
                {
                    storeIDList = new List<int>()
                    {
                        sysStoreID
                    };
                }
                //是否是我能访问到的
                using var dbNoFilter = DbNoFilter;
                SysFile beforeFile = dbNoFilter.SysFile.OrderByDescending(m => storeIDList.Contains(m.SysStoreID))
                    .FirstOrDefault(m => m.FileMD5 == md5 && m.ID != model.ID);
                if (beforeFile != null && !string.IsNullOrEmpty(beforeFile.FilePath))
                {
                    try
                    {
                        System.IO.File.Delete(localFile);
                    }
                    catch (Exception ex)
                    {
                    }
                    if (model.NoAddMore && storeIDList.Contains(beforeFile.SysStoreID))
                    {
                        beforeFile.UpdateDate = DateTime.Now;
                        dbNoFilter.SaveChanges();

                        r.Message = "已存在此文件:" + model.SysFileName;
                        r.Result = beforeFile;
                        r.Success = true;
                        //直接返回1.是true的
                        r.Total = 1;
                        return r;
                    }
                    model.FilePath = beforeFile.FilePath;
                }
                model.FileMD5 = md5;

                #endregion
            }
            if (string.IsNullOrEmpty(model.FilePath))
            {
                r.Message = "请选择上传文件";
                return r;
            }
            //if (string.IsNullOrEmpty(model.FileMD5))
            //{
            //    r.Message = LanguageHelper.RequireString1<SysFile>(nameof(SysFile.FileMD5));
            //    return r;
            //}
            model.PY = ToolHelper.GetPy(model.SysFileName);
            model.UpdateSysEmployeeID = CurrentEmployee?.SysEmployeeID;
            model.UpdateDate = DateTime.Now;

            var extention = System.IO.Path.GetExtension(model.FilePath)?.ToLower();
            if (string.IsNullOrEmpty(extention))
            {
                r.Message = "文件有误,未获取到文件后缀";
                return r;
            }
            extention = extention.Replace(".", string.Empty);
            if (model.SysFileName.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1)
            {
                var extention2 = System.IO.Path.GetExtension(model.SysFileName).ToLower().Replace(".", string.Empty);
                if (extention2 != extention)
                {
                    if (extention2 == "jpg") extention2 = "jpeg";
                    if (extention2 != extention)
                    {
                        try
                        {
                            System.IO.File.Delete(localFile);
                        }
                        catch (Exception ex)
                        {
                        }

                        r.Message = "不支持的文件格式,上传失败";
                        return r;
                    }
                }
            }
            if (Base64Helper.ImageFileExtentions.Contains(extention))
            {
                model.EnumFileType = EnumFileType.图片;
            }
            else if (Base64Helper.OfficeFileExtentions.Contains(extention))
            {
                model.EnumFileType = EnumFileType.Office文件;
            }
            else
            {
                model.EnumFileType = EnumFileType.其它文件;
            }
            if (isAdd)
            {
                model.SysStoreID = CurrentStore.SysStoreID;
            }
            r = ValidatePartial(model, isAdd, r, db);
            if (r.Success == false) return r;
            r.Success = true;
            return r;
        }

        #endregion

        #region 分页方法

        /// <summary>
        /// 查询条件,能替换掉一些属性查询为自定义查询
        /// </summary>
        /// <param name="where"></param>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        private Expression<Func<SysFile, bool>> InitSearchDelegete(Expression<Func<SysFile, bool>> where, string key, string val, DbEntities db)
        {
            var r = InitSearchDelegetePartial(where, key, val, db);
            if (r != null) return r;
            //-1代表全部
            if (key == "EnumFileType" && val == "-1")
            {
                return where;//return null代表走默认处理;return where代表忽略掉此字段
            }
            return null;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="index"></param>
        /// <param name="size"></param>
        /// <param name="form"></param>
        /// <param name="sortField"></param>
        /// <param name="asc"></param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> GetListByPage(int index, int size, IFormCollection form = null, string sortField = "UpdateDate", bool asc = false)
        {
            using (var db = Db)
            {
                Expression<Func<SysFile, bool>> where = InitSearch<SysFile, DbEntities>(form, InitSearchDelegete, db); //拼接查询条件方法
                IQueryable<SysFile> query = OrderByPartial(db.SysFile, sortField, asc, db);
                int counts;
                var tempIDList = query.ExGetListByPage(index, size, out counts, where).Select(m => m.ID);
                var r = new AjaxResult<dynamic>();
                r.Total = counts;
                IQueryable<SysFile> list = query.Where(m => tempIDList.Contains(m.ID));
                var tempList = list.Select(m => new
                {
                    ID = m.ID,
                    SysStoreID = m.SysStoreID,
                    SysStore = new SysStore()
                    {
                        SysStoreID = m.SysStore.SysStoreID,
                        EnumSysStoreType = m.SysStore.EnumSysStoreType,
                        SysStoreName = m.SysStore.SysStoreName,
                        PhoneNumber = DbFun.fn_replaceNum(m.SysStore.PhoneNumber, CanSeePhone),
                        EnumStatus = m.SysStore.EnumStatus
                    },
                    SysDicID = m.SysDicID,
                    SysDic = new
                    {
                        SysDicID = (int?)m.SysDic.SysDicID,
                        SysDicName = m.SysDic.SysDicName
                    },
                    EnumFileType = m.EnumFileType,
                    SysFileName = m.SysFileName,
                    FilePath = m.FilePath,
                    FileMD5 = m.FileMD5,
                    PY = m.PY,
                    OrderID = m.OrderID,
                    UpdateSysEmployeeID = m.UpdateSysEmployeeID,
                    UpdateDate = m.UpdateDate,
                    IsDel = m.IsDel,
                    Remark = m.Remark
                });
                var resultList = await tempList.ToListAsync();
                //return GetListByPagePartial(resultList, r, db);

                r.Success = true;
                r.Result = resultList;
                return r;
            }
        }

        #endregion

        #region 得到单对象,返回值有可能为null

        /// <summary>
        /// 得到单对象,返回值有可能为null
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        public async Task<AjaxResult<SysFile>> GetModel(int id)
        {
            using (var db = Db)
            {
                return await GetModel(id, db);
            }
        }

        internal async Task<AjaxResult<SysFile>> GetModel(int id, DbEntities db)
        {
            string include = GetModelIncludePartial();
            IQueryable<SysFile> query = !string.IsNullOrWhiteSpace(include) ? db.SysFile.Include(include) : db.SysFile;
            var temp = query.Where(m => m.ID == id);
            var dbModel = await temp.FirstOrDefaultAsync();
            return GetModelReturnPartial(dbModel, db);
        }

        #endregion

        #region 保存数据

        /// <summary>
        /// 保存数据
        /// </summary>
        /// <param name="model">保存的对象,成功之后model对象的model对象的主键能得到对象</param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Save(SysFile model)
        {
            using (var db = Db)
            {
                if (this.SaveJudgePartial(model, db))
                {
                    return await Add(model, db);
                }
                return await Update(model, db);
            }
        }

        #endregion

        #region 添加数据

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Add(SysFile model)
        {
            using (var db = Db)
            {
                return await Add(model, db);
            }
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal async Task<AjaxResult<dynamic>> Add(SysFile model, DbEntities db)
        {
            var r = new AjaxResult<dynamic>() { Success = false };
            if (db == null) db = Db;
            var tempAr = Validate(model, true, db);
            if (tempAr.Success == false)
            {
                r.Message = tempAr.Message;
                r.Result = tempAr.Result;
                r.Total = tempAr.Total;
                return r;
            }
            if (tempAr.Total == 1)
            {
                r.Message = tempAr.Message;
                r.Result = tempAr.Result;
                r.Total = tempAr.Total;
                r.Success = tempAr.Success;
                return r;
            }
            var tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
            try
            {
                db.SysFile.Add(model);
                string error = AddLog(db, model, EnumLogType.新建);
                if (!string.IsNullOrEmpty(error))
                {
                    return AjaxResult<dynamic>.ErrorResult(error);
                }
                await db.SaveChangesAsync();
                r = AddUpdateSuccessPartial(model, true, r, db);
                if (r.Success == false)
                {
                    return r;
                }
                await db.SaveChangesAsync();
                if (hasTran == false)
                {
                    await tran.CommitAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
                r.Success = true;
                r.Message = LanguageHelper.Success;
                r.Result = model;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError(GetCurrentOther());
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null)
                {
                    await tran.RollbackAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
            }
        }

        #endregion

        #region 编辑Old

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Update(SysFile model)
        {
            using (var db = Db)
            {
                return await Update(model, db);
            }
        }

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal async Task<AjaxResult<dynamic>> Update(SysFile model, DbEntities db)
        {
            var r = new AjaxResult<dynamic>() { Success = false };
            if (db == null) db = Db;
            var tempAr = Validate(model, false, db);
            if (tempAr.Success == false)
            {
                r.Message = tempAr.Message;
                r.Result = tempAr.Result;
                r.Total = tempAr.Total;
                return r;
            }
            if (tempAr.Total == 1)
            {
                r.Message = tempAr.Message;
                r.Result = tempAr.Result;
                r.Total = tempAr.Total;
                r.Success = tempAr.Success;
                return r;
            }
            var tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
            try
            {
                var dbModel = await db.SysFile.FirstOrDefaultAsync(m => m.ID == model.ID);
                if (dbModel == null)
                {
                    r.Message = LanguageHelper.NoData;
                    return r;
                }

                dbModel.SysDicID = model.SysDicID;
                dbModel.EnumFileType = model.EnumFileType;
                dbModel.SysFileName = model.SysFileName;
                dbModel.FilePath = model.FilePath;
                dbModel.FileMD5 = model.FileMD5;
                dbModel.OrderID = model.OrderID;
                dbModel.Remark = model.Remark;
                dbModel.PY = model.PY;
                dbModel.UpdateSysEmployeeID = model.UpdateSysEmployeeID;
                dbModel.UpdateDate = model.UpdateDate;

                string error = AddLog(db, model, EnumLogType.编辑);
                if (!string.IsNullOrEmpty(error))
                {
                    return AjaxResult<dynamic>.ErrorResult(error);
                }
                await db.SaveChangesAsync();
                r = AddUpdateSuccessPartial(model, false, r, db, dbModel);
                if (r.Success == false)
                {
                    return r;
                }
                await db.SaveChangesAsync();
                if (hasTran == false)
                {
                    await tran.CommitAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
                r.Success = true;
                r.Message = LanguageHelper.Success;
                r.Result = dbModel;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError(GetCurrentOther());
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null)
                {
                    await tran.RollbackAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
            }
        }

        #endregion

        //#region 编辑New

        ///// <summary>
        ///// 编辑
        ///// </summary>
        ///// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        ///// <returns></returns>
        //public async Task<AjaxResult<dynamic>> Modify(SysFile model)
        //{
        //    using (var db = Db)
        //    {
        //        return await Modify(model, db);
        //    }
        //}

        ///// <summary>
        ///// 编辑
        ///// </summary>
        ///// <param name="model">添加的对象,成功之后model对象的主键能得到对象</param>
        ///// <param name="db"></param>
        ///// <returns></returns>
        //internal async Task<AjaxResult<dynamic>> Modify(SysFile model, DbEntities db)
        //{
        //    var r = new AjaxResult<dynamic>() { Success = false };
        //    if (db == null) db = Db;
        //    var tempAr = Validate(model, false, db);
        //    if (tempAr.Success == false)
        //    {
        //        r.Message = tempAr.Message;
        //        r.Result = tempAr.Result;
        //        r.Total = tempAr.Total;
        //        return r;
        //    }
        //    var tran = db.Database.CurrentTransaction;
        //    bool hasTran = tran != null;
        //    if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
        //    try
        //    {
        //        //排除掉SysStoreID 才能使用
        //        await ModifyBaseAsync(model, db, typeof(SysFile));

        //        string error = AddLog(db, model, EnumLogType.编辑);
        //        if (!string.IsNullOrEmpty(error))
        //        {
        //            return AjaxResult<dynamic>.ErrorResult(error);
        //        }
        //        await db.SaveChangesAsync();
        //        r = AddUpdateSuccessPartial(model, false, r, db);
        //        if (r.Success == false)
        //        {
        //            return r;
        //        }
        //        await db.SaveChangesAsync();
        //        if (hasTran == false)
        //        {
        //            await tran.CommitAsync();
        //            await tran.DisposeAsync();
        //            tran = null;
        //        }
        //        r.Success = true;
        //        r.Message = LanguageHelper.Success;
        //        r.Result = model;
        //        return r;
        //    }
        //    catch (Exception ex)
        //    {
        //        ex.ExLogError(GetCurrentOther());
        //        r.Total = (int)EnumTotal.异常;
        //        r.Success = false;
        //        r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
        //        return r;
        //    }
        //    finally
        //    {
        //        if (hasTran == false && tran != null)
        //        {
        //            await tran.RollbackAsync();
        //            await tran.DisposeAsync();
        //            tran = null;
        //        }
        //    }
        //}

        //#endregion

        #region 删除

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> Del(int id)
        {
            using (var db = Db)
            {
                return await Del(id, db);
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal async Task<AjaxResult<dynamic>> Del(int id, DbEntities db)
        {
            var r = new AjaxResult<dynamic>() { Success = false };
            if (db == null) db = Db;
            var tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = await db.Database.BeginTransactionAsync();
            try
            {
                var dbModel = await db.SysFile.FirstOrDefaultAsync(m => m.ID == id);
                if (dbModel == null)
                {
                    r.Message = LanguageHelper.NoData;
                    return r;
                }

                r = DelValidatePartial(dbModel, r, db);
                if (r.Success == false)
                {
                    return r;
                }
                //db.SysFile.Remove(dbModel);
                dbModel.IsDel = true;
                string error = AddLog(db, dbModel, EnumLogType.删除);
                if (!string.IsNullOrEmpty(error))
                {
                    return AjaxResult<dynamic>.ErrorResult(error);
                }
                await db.SaveChangesAsync();
                r = DelSuccessPartial(dbModel, r, db);
                if (r.Success == false)
                {
                    return r;
                }
                await db.SaveChangesAsync();
                if (hasTran == false)
                {
                    await tran.CommitAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
                r.Success = true;
                r.Message = LanguageHelper.Success;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError(GetCurrentOther());
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = string.Format(LanguageHelper.Fail1, ex.ExMessageWithInner());
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null)
                {
                    await tran.RollbackAsync();
                    await tran.DisposeAsync();
                    tran = null;
                }
            }
        }

        #endregion

        #region 下拉选择

        /// <summary>
        /// 下拉选择
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public async Task<AjaxResult<dynamic>> GetListSelect(IFormCollection form = null)
        {
            using (var db = Db)
            {
                Expression<Func<SysFile, bool>> where = InitSearch<SysFile, DbEntities>(form, InitSearchDelegete, db); //拼接查询条件方法
                var selectID = form["selectIDName"].ExTrim();
                var obj = db.SysFile.AsNoTracking();
                bool hasSelectID = false;
                if (!string.IsNullOrEmpty(selectID))
                {
                    if (selectID.IndexOf(',') != -1)
                    {
                        var selectIDList = selectID.ExToSplitList(',', false);
                        if (selectIDList.Count > 0)
                        {
                            hasSelectID = true;
                            obj = obj.OrderByDescending(m => selectIDList.Contains(m.ID)).ThenByDescending(m => m.ID);
                        }
                    }
                    else
                    {
                        var selectIDInt = selectID.ExToInt32();
                        if (selectIDInt > 0)
                        {
                            hasSelectID = true;
                            obj = obj.OrderByDescending(m => selectIDInt == m.ID).ThenByDescending(m => m.ID);
                        }
                    }
                    if (hasSelectID == false)
                    {
                        obj = obj.OrderByDescending(m => m.ID);
                        where = where.ExAnd(m => m.SysFileName.Contains(selectID) || m.PY.Contains(selectID));
                    }
                }
                if (hasSelectID == false)
                {
                    obj = obj.OrderByDescending(m => m.ID);
                    //where = where.ExAnd(m => m.EnumStatus == EnumStatus.启用);
                }
                var result = new AjaxResult<dynamic>() { Success = true };
                IQueryable<SysFile> list = obj.Where(where).Take(DefaultSize);
                var tempList = list.Select(m => new
                {
                    ID = m.ID,
                    SysStoreID = m.SysStoreID,
                    //SysStore = new SysStore()
                    //{
                    //    SysStoreID = m.SysStore.SysStoreID,
                    //    EnumSysStoreType = m.SysStore.EnumSysStoreType,
                    //    SysStoreName = m.SysStore.SysStoreName,
                    //    PhoneNumber = DbFun.fn_replaceNum(m.SysStore.PhoneNumber, CanSeePhone),
                    //    EnumStatus = m.SysStore.EnumStatus
                    //},
                    SysDicID = m.SysDicID,
                    //SysDic = new SysDic()
                    //{
                    //    SysDicID = m.SysDic.SysDicID,
                    //    SysDicName = m.SysDic.SysDicName
                    //},
                    EnumFileType = m.EnumFileType,
                    SysFileName = m.SysFileName,
                    FilePath = m.FilePath,
                    FileMD5 = m.FileMD5,
                    PY = m.PY,
                    OrderID = m.OrderID,
                    UpdateSysEmployeeID = m.UpdateSysEmployeeID,
                    UpdateDate = m.UpdateDate,
                    IsDel = m.IsDel,
                    Remark = m.Remark
                });
                result.Result = await tempList.ToListAsync();
                return result;
            }
        }

        #endregion

        //#region 导入
        //#endregion
    }
}
